require 'depac-common/log'
require 'depac-common/constants'
require 'depac-common/constants_cbt'
require 'fileutils'
require 'yaml'
require 'erubis'

module Depac
  class DeploymentCBT
    attr_accessor :artifactMapPath,:artifactsDir,:aggregatedArtifactMap
    
    private     
    def initialize(buildlabel)
         Depac::Log.info("Initial DeploymentCBT Class.........")
         @aggregatedArtifactMap=Hash.new
         @artifactMapPath=nil
         
         #add below line for testing
         # @aggregatedArtifactMap={"wars"=>{ "trade"=>{"location" => "war package location",
         #                                           "packageName" => "trade-web",
         #                                           "localLocation" => ""
         #                                          } 
         #                                },
         #                         "schema"=>{ "trade"=>{"location" => "schema location",
         #                                              "packageName" => "trade",
         #                                              "localLocation" => ""
         #                                              } 
         #                                   }       
         #                        }

         
         @artifactsDir=Depac::DeploymentConstants_CBT::DefaultArtifactLocation+"/#{buildlabel}"
    end
  
    public   
    
    def deploySchema(nodeInfoMap, buildlabel, envconfig)
         Depac::Log.info("deployment_cbt.deploySchema: start deploy schema on target servers.........")
         nodeInfoMap.each do |role, nodeInfoArr|
              if role.include?("db")
                    Depac::Log.info("deployment_cbt.deploySchema: Detected db role -> #{role}.........")
                    nodeInfoArr.each do |node|
                         if node['schema'] != nil
                              schemaArr=node['schema'].split(",")
                              Depac::Log.info("deployment_cbt.deploySchema: handle db node #{node['hostname']} with schemas-> #{node['schema']}.........")
                              Depac::Log.info("deployment_cbt.deploySchema: node info -> #{node}.........")
                              

                              schemaArr.each do |schema|
                                     #Depac::Log.info("deployment_cbt.deploySchema: schema path -> #{Depac::DeploymentConstants_CBT::DefaultArtifactLocation}/#{buildlabel}/schema/#{schema}.sql")
                                     Depac::Log.info("can not find schema file with path #{Depac::DeploymentConstants_CBT::DefaultArtifactLocation}/#{buildlabel}/schema/#{schema}.sql") if ! File.exist?(Depac::DeploymentConstants_CBT::DefaultArtifactLocation+"/#{buildlabel}/schema/#{schema}.sql")

                                     if node['IP'] !=nil && File.exist?(Depac::DeploymentConstants_CBT::DefaultArtifactLocation+"/#{buildlabel}/schema/#{schema}.sql")
                                          uploadSchemaCMD="scp -o StrictHostKeyChecking=no -i #{Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH} #{@artifactsDir}/schema/#{schema}.sql root@#{node['IP']}:/tmp"
                                          Depac::Log.info("deployment_cbt.deploySchema.uploadSchemaCMD-> #{uploadSchemaCMD}.........")

                                          if Utils.logged_remoteExec(uploadSchemaCMD, "deployment_cbt.deploySchema.uploadSchema: ") then Log.fatal_exit("Error while upload #{schema}.sql to server #{node['IP']} fail......") end 
                                               
                                          importSchemaCMD="ssh -t -t -i #{Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH} root@#{node['IP']} -o StrictHostKeyChecking=no \"bash --login -c 'cd /tmp;mysql -u#{envconfig['mysql']['dbuser']} -p#{envconfig['mysql']['dbpassword']} </tmp/#{schema}.sql'\""
                                          Depac::Log.info("deployment_cbt.deploySchema.importSchemaCMD-> #{importSchemaCMD}.........")
                                          if Utils.logged_remoteExec(importSchemaCMD, "deployment_cbt.deploySchema.importSchema: ") then Log.fatal_exit("Error while import #{schema}  to server #{node['IP']} fail......") end                                                                                 
                                     end
                              end             
                         end
                    end
              end
         end
    end


       
    #This methode used to deploy war package to tomcat
    #1. generate web module property
    #2. loop all war file and repackage them and deploy them one by one
    # ###########################
    #will using variable @aggregatedArtifactMap 
    # ########################### 
    def deployApp(nodeInfoMap, buildlabel, envconfig, isUpdate, sleepTime=nil) 
          Depac::Log.info("deployment_cbt.deployApp: start deploy App on target servers.........")   
          nodeInfoMap.each do |role, nodeInfoArr|
                 if role.include?("app")
                       Depac::Log.info("deployment_cbt.deployApp: Detected app role -> #{role}.........")
                       nodeInfoArr.each do |appNode|
                            
                            if sleepTime
                                   Depac::Log.info("deployment_cbt.deployApp: sleep #{sleepTime}s before deploy start.........")  
                                   sleep sleepTime                           
                            end
                            
                            
                            if isUpdate && envconfig['autoOfflineNodeOnLB']
                                  if appNode['lb_backend_Config']!=nil && appNode['lb_backend_IDs']!=nil                     
                                        appNode['lb_backend_IDs'].each do |lb_backend_ID|
                                              Depac::Log.info("deployment_cbt.deployApp: offline LB backend #{lb_backend_ID}.........")
                                              $cloudmgr.backendDisable?(lb_backend_ID)
                                        end
                                  end
                            end
                            
                            warsArr=appNode["wars"].split(",")
                            Depac::Log.info("deployment_cbt.deployApp: Detected war spcify--> #{warsArr} on #{appNode['hostname']}.........")
                            warsArr.each do |_war| 
                                 # for each war should generate special property file
                                 generateResource(nodeInfoMap, appNode, buildlabel, _war, envconfig)            
                                 _packageName=repackageWar(_war, buildlabel)
                                 deployWar(_packageName,appNode["IP"],nil)
                            end                           
                            removeModulePropCMD="rm -rf #{Depac::DeploymentConstants_CBT::DefaultArtifactLocation}/#{buildlabel}/temp/web-module-resources-default.properties"
                            if Utils.logged_exec(removeModulePropCMD,"deployment_cbt.deployApp.removeOldModuleProp: ", true)  then Log.fatal_exit("Error while remove web-module-resources-default.properties after repackage war for #{appNode['hostname']}") end           
                       
                            if isUpdate
                                 # here need to add command to stop tomcat 
                                 stopTomcatCMD = "ssh -t -t -i #{Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH} root@#{appNode["IP"]} -o StrictHostKeyChecking=no \"bash --login -c '/usr/local/tomcat/bin/shutdown.sh'\""
                                 Depac::Log.info("deployment_cbt.deployApp.restartTomcatCMD: #{stopTomcatCMD}.........")
                                 if Utils.logged_remoteExec(stopTomcatCMD, "deployment_cbt.deployWar.stopTomcatCMD: ") then Log.fatal_exit("Error while stop tomcat on server #{appNode["IP"]}......"); end
                                 
                                 sleep 30
                                 
                                 # here need to add command to start tomcat 
                                 startTomcatCMD = "ssh -t -t -i #{Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH} root@#{appNode["IP"]} -o StrictHostKeyChecking=no \"bash --login -c 'nohup /usr/local/tomcat/bin/startup.sh'\""
                                 Depac::Log.info("deployment_cbt.deployApp.restartTomcatCMD: #{startTomcatCMD}.........")
                                 if Utils.logged_remoteExec(startTomcatCMD, "deployment_cbt.deployWar.startTomcatCMD: ") then Log.fatal_exit("Error while start tomcat on server #{appNode["IP"]}......"); end
                            end
                             
                            if sleepTime
                                Depac::Log.info("deployment_cbt.deployApp: sleep #{sleepTime}s after deploy finish.........")  
                                sleep sleepTime                           
                            end
                            
                            
                            if isUpdate && envconfig['autoOnlineNodeOnLB']
                                  if appNode['lb_backend_Config']!=nil && appNode['lb_backend_IDs']!=nil                                                                                                           
                                              appNode['lb_backend_IDs'].each do |lb_backend_ID|
                                                  Depac::Log.info("deployment_cbt.deployApp: online LB backend #{lb_backend_ID}.........")   
                                                  $cloudmgr.backendDisable?(lb_backend_ID,0)
                                              end
                                  end          
                            end                      
                       end                  
                 end
          end
    end
    
    # ###################
    #Deploye war package
    #the packageName already with .zip
    # ###################
    def deployWar(packageName, targetIP, dir=nil)      
          Depac::Log.info("deployment_cbt.deployWar: deploy #{@artifactsDir}/temp/#{packageName} on server #{targetIP}.........")

          if File.exist?("#{@artifactsDir}/temp/#{packageName}")          
             #copy war package to tmp directory
             deployCMD = "scp -o StrictHostKeyChecking=no -i #{Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH} #{@artifactsDir}/temp/#{packageName} root@#{targetIP}:#{Depac::DeploymentConstants_CBT::CBT_NODE_TEMP_PATH}"
             Depac::Log.info("deployment_cbt.deployWar.deployCMD: #{deployCMD}.........")
             if Utils.logged_remoteExec(deployCMD, "deployment_cbt.deployWar.copyWar: ") then Log.fatal_exit("Error while copy war package to server #{targetIP}......"); end
    
             #unzip war package to webapps
             unzipCMD = "ssh -t -t -i #{Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH} root@#{targetIP} -o StrictHostKeyChecking=no 'cd /tmp;unzip -oq #{packageName} -d #{Depac::DeploymentConstants_CBT::CBT_TOMCATE_WEBAPPS_PATH}'"
             Depac::Log.info("deployment_cbt.deployWar.unzipCMD: #{unzipCMD}.........")
             if Utils.logged_remoteExec(unzipCMD, "deployment_cbt.deployWar.unzipWar: ") then Log.fatal_exit("Error while unzip war package to server #{targetIP} fail......"); end         
          else
             Depac::Log.info("deployment_cbt.deployWar: can not find target war package with path #{@artifactsDir}/temp/#{packageName}!")   
          end
    end
    
    
    
    #1. unzip war to /tmp/warnmae
    #2. replace web-module-resources.properties from <buildlabe>/web-module-resources.properties to /waranme/WEB-INF/classes/web-module-resources.properties
    #3. zip warname in temp folder and deploywar
    def repackageWar(warName, buildlabel)
    
           #1. unzip war
           #2. replace property
           #3. zip war
           Depac::Log.info("deployment_cbt.repackageWar: repackage #{warName}.........")
           
           warInfoMap=@aggregatedArtifactMap["wars"]
           if warInfoMap!=nil && warInfoMap.has_key?(warName)           
                warInfo=warInfoMap[warName]
                
                system("rm -rf #{@artifactsDir}/temp/#{warInfo["packageName"]}")
                
                unzipWarCMD="cd #{@artifactsDir}/web;unzip -oq #{warInfo["packageName"]}.war -d #{@artifactsDir}/temp/#{warInfo["packageName"]}"
                Depac::Log.info("deployment_cbt.repackageWar.unzipWarCMD:  #{unzipWarCMD}.........")
                if Utils.logged_exec(unzipWarCMD,"deployment_cbt.repackageWar", true) then Log.fatal_exit("Error while unzip war #{warName} package fail......") end           
           
                  
                if File.exist?(Depac::DeploymentConstants_CBT::CBT_WAR_RESOURC_MAPPING_PATH)     
                     warRSMap_Hash=YAML.load_file(File.expand_path(Depac::DeploymentConstants_CBT::CBT_WAR_RESOURC_MAPPING_PATH))           
                     if warRSMap_Hash.has_key?(warName) 
                         warRSMap_Hash[warName].each do |propertyName, relatedPath|
                            
                               if File.exist?(@artifactsDir+"/temp/#{propertyName}") 
                                                  replaceCMD="cd #{@artifactsDir}/temp; cp -f #{propertyName}  #{warInfo["packageName"]}/#{relatedPath}"
                                                  Depac::Log.info("deployment_cbt.repackageWar.replaceCMD:  #{replaceCMD}.........")
                                                  if Utils.logged_exec(replaceCMD,"deployment_cbt.replace-#{propertyName} ", true) then Log.fatal_exit("Error while replace #{propertyName} for #{warName} war package......"); end         
                               end 
                               
                          end                 
                     end
                end
                  
                #just do replacement when find web-module-resources-default.properties exist
                #if File.exist?(@artifactsDir+"/temp/web-module-resources.properties") 
                #      replaceCMD="cd #{@artifactsDir}/temp; cp -f web-module-resources.properties  #{warInfo["packageName"]}/#{Depac::DeploymentConstants_CBT::WEBMUDLEPROP_PARENTDIR}"
                #      Depac::Log.info("deployment_cbt.repackageWar.replaceCMD:  #{replaceCMD}.........")
                #      if Utils.logged_exec(replaceCMD,"deployment_cbt.replace-web-module-resource-properites ", true) then Log.fatal_exit("Error while replace web module properties for #{warName} war package......"); end         
                #end 
                
                #just do replacement when find container-service-registry.xml exist
                #if File.exist?(@artifactsDir+"/temp/container-service-registry.xml")
                #     replaceCMD="cd #{@artifactsDir}/temp; cp -f container-service-registry.xml  #{warInfo["packageName"]}/#{Depac::DeploymentConstants_CBT::WEBMUDLEPROP_PARENTDIR}"
                #     Depac::Log.info("deployment_cbt.repackageWar.replaceCMD:  #{replaceCMD}.........")
                #end
                
                Depac::Log.info("deployment_cbt.repackageWar.zipWarCMD:  add build version #{buildlabel} into war package #{warInfo["packageName"]}.........")
                system("echo #{buildlabel} > #{@artifactsDir}/temp/#{warInfo["packageName"]}/version")                               
                
                #re-zip war package
                zipWarCMD="cd #{@artifactsDir}/temp;zip -r #{warInfo["packageName"]}.zip #{warInfo["packageName"]}"
                Depac::Log.info("deployment_cbt.repackageWar.zipWarCMD:  #{zipWarCMD}.........")
                if Utils.logged_exec(zipWarCMD,"deployment_cbt.repackageWar.zipWar: ", true) then Log.fatal_exit("Error while re-zip #{warName} war package......"); end                                       
           end 
           
           return  "#{warInfo["packageName"]}.zip" 
    end
    
    
    # #############################################
    # This is main mehtod will be called to deploy CBT
    # #############################################
    def deploy(nodeInfoMap,buildlabel,envconfig)
    
        #step1: get artifacts
        getArtifacts(nodeInfoMap, buildlabel, envconfig)
                
        #step3: configure hosts for each node
        configureHostsMapping(nodeInfoMap)
        
        #step4: deploySchema
        deploySchema(nodeInfoMap, buildlabel, envconfig)
        
        #setp5: deployApp
        deployApp(nodeInfoMap, buildlabel, envconfig, false) 
        
    end
    
    # #######################################################
    #so far just app type need to configure other node's host
    # #######################################################
    def configureHostsMapping(nodeInfoMap)
          hostMapConfig=YAML.load_file(File.expand_path(Depac::DeploymentConstants_CBT::CBT_HOSTMAPTING_YAML_PATH))
          
          nodeInfoMap.each do |role, nodeInfoArr|
                   if hostMapConfig.has_key?(role)
                      roleHostMapping=hostMapConfig[role]
                      Depac::Log.info("Detected role-->#{role} has hosts mapping need to be configured #{hostMapConfig[role]}.........")
                          nodeInfoArr.each do |node|
                                
                                targetIP=node['IP']
                          
                                if node['linkto'] != nil
                                
                                      linktoArr=node['linkto']
                                      Depac::Log.info("get linkto array: #{linktoArr}.node.....................")
                                      linktoArr.each do |linktoInfo|
                                           linktoInfo.each do |linkrole,linkInfo|
                                                  Depac::Log.info("get linktoInfo: #{linktoInfo}.....................")
                                                  Depac::Log.info("get roleHostMapping: #{roleHostMapping}.....................")
                                                  if roleHostMapping.has_key?(linkrole) && linkInfo !=nil
                                                         
                                                         _ip=nil
                                                         
                                                        Depac::Log.info("deployment_cbt.configureHostsMapping get linkInfo #{linkInfo}.........")                               
                                                        if linkInfo !=nil && linkInfo['IP'] !=nil                                                             
                                                             _ip=linkInfo['IP']
                                                        elsif linkInfo !=nil && linkInfo['IP'] == nil && linkInfo['index'] !=nil
                                                             _ip=getIPbyRoleAndIndex(nodeInfoMap, linkrole, linkInfo['index'] )
                                                        else
                                                             _ip=getIPbyRoleAndIndex(nodeInfoMap, linkrole, 1)
                                                             Depac::Log.info("Not find specified vm, will find the related vm in new created list with index 1.........")
                                                        end
                                                        
                                                        _hostnames=roleHostMapping[linkrole]
                                                        _hostnameArray=_hostnames.split(';') 
                                                       
                                                        Depac::Log.info("deployment_cbt.configureHostsMapping get #{_ip} #{_hostnameArray} to configure on  server #{targetIP}.........")  
                                                        _hostnameArray.each do | _hostname |
                                                           if _ip !=nil && _hostname !=nil
                                                              hostKeyValue="#{_hostname}:#{_ip}"
                                                              setHostCMD = "ssh -t -t -i #{Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH} root@#{targetIP} -o StrictHostKeyChecking=no 'cd /scripts;./configureHosts.sh #{hostKeyValue}'"
                                                              #setHostCMD = "ssh -t -t -i #{Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH} root@#{targetIP} -o StrictHostKeyChecking=no 'echo #{_ip} #{_hostname} >> /etc/hosts '"                                                            
                                                              if Utils.logged_remoteExec(setHostCMD, "deployment_cbt.configureHostsMapping.setHosts: ") then Log.fatal_exit("Error while set host #{_ip} #{_hostname} to server #{targetIP} fail......"); end 
                                                              Depac::Log.info("deployment_cbt.configureHostsMapping set #{_ip} #{_hostname} to server #{targetIP}.........")                                                                   
                                                           end 
                                                        end    
                                                  end
                                           end
                                      end                               
                                end  
                          end
                   end
          end
                  
    end
    
    # ############################################################
    #This method used to get the IP by specified role and node index in nodeInfo based on meta data nodeInfoMap 
    # ############################################################ 
    def getIPbyRoleAndIndex(nodeInfoMap, role, nodeIndex)
        
        _ip =nil     
        nodeInfoMap.each do |_role, nodeInfoArr|
              if _role == role && nodeInfoArr.size >= nodeIndex-1             
                   nodeInfo= nodeInfoArr[nodeIndex-1]                 
                   _ip=nodeInfo['IP'] if nodeInfo['IP'] !=nil           
                   break            
              end
        end              
        return _ip
    end
    
    # ###############################
    #the meta data (@aggregatedArtifactMap) should be:
    #wars:
    #    cart:
    #       location: _location
    #       packageName: _artifact
    #       localLocation: nil
    #    payment:
    #       .....
    #schema:
    #    cart: 
    #       location: _location
    #       packageName: _artifact
    #       localLocation: nil
    # ###############################
    def getArtifacts(nodeInfoMap, buildlabel, envconfig)
         #if buildlabel folder exist rm it
         #create a new buildlabel folder with sub-folder web temp schema
         #load cbt-artifact-location.yml as a hash table
         
         @aggregatedArtifactMap=Hash.new
         
         artifactsDir=Depac::DeploymentConstants_CBT::DefaultArtifactLocation+"/#{buildlabel}"
         
         if File.directory?(artifactsDir)
              removeCMD="rm -rf #{artifactsDir}"
              Utils.logged_exec(removeCMD,"deployment_cbt.getArtifacts.removeExistArtifactsFolder", true) 
         end
         
         createCMD="mkdir -p  #{artifactsDir}/web;mkdir -p  #{artifactsDir}/temp;mkdir -p   #{artifactsDir}/schema" 
         Utils.logged_exec(createCMD,"deployment_cbt.getArtifacts.createtArtifactsFolder", true)   
         
         #if customized aritfactlocationMapPath, will using customized
         if @artifactMapPath==nil
           if envconfig['cusArtifactLocationMapPath'] !=nil
              @artifactMapPath=envconfig['cusArtifactLocationMapPath']
           else
              @artifactMapPath=Depac::DeploymentConstants_CBT::DefaultArtifactLocationMapPath
           end
         end
         Depac::Log.write("INFO", "artifact download location mapping file path is #{@artifactMapPath}") 
         
         #stored the artifact location path as url on nexus repositories server
         artifactMap=YAML.load_file(File.expand_path(@artifactMapPath))
         
         nodeInfoMap.each do |role, nodeInfoArray|               
                case role
                
                when 'app-tomcat', 'app-liberty'
                
                      @aggregatedArtifactMap["wars"]=aggregateArtifact(nodeInfoArray,artifactMap,role)         
                
                when 'db-mysql', 'db-db2'
                
                      @aggregatedArtifactMap["schema"]=aggregateArtifact(nodeInfoArray,artifactMap,role)  
                else
                   Depac::Log.write("INFO", "This is role don't have any artifact need to download........")                
                end        
         end        
         downloadArtifacts(@aggregatedArtifactMap , buildlabel)      
    end
    
    # #######################################
    # This method used to download artifact from nexus or git
    # #######################################
    def downloadArtifacts(aggregatedArtifactMap, buildlabel)
    
          aggregatedArtifactMap.each do |type, artifactHashMap|
          
               case type
               
               when "wars"
                   #1. getArtifact from nexuse
                   #2. generateWebModuleProperty                  
                   #3. repackage (unzip war / replace property/ zip it to web folder/ change locallocation)
                   
                   targetPath = Depac::DeploymentConstants_CBT::DefaultArtifactLocation+"/"+buildlabel+"/web"
                   
                   artifactHashMap.each do |warName, warInfo|
                         downloadArtifactFromNexus(warInfo["location"],targetPath, warInfo['packageName']+".war")
                         warInfo["locallocation"]=targetPath+"/#{warInfo['packageName']}.war"
                   end     
                                
               when "schema"
               
                   targetPath = Depac::DeploymentConstants_CBT::DefaultArtifactLocation+"/"+buildlabel+"/schema"
                   
                   artifactHashMap.each do |schemaName, schemaInfo|
                         #downloadArtifactFromGit(schemaInfo["location"],targetPath)
                         downloadArtifactByWget(schemaInfo["location"], targetPath)
                         schemaInfo["locallocation"]=targetPath+"/"+schemaName+".sql"
                   end 
                           
               else
                  Depac::Log.write("INFO", "unknow artifact type-->#{type}, will ignore it.........") 
               end      
          end          
    end
    
    # ##########################
    # download artifact nexus
    # ##########################
    def downloadArtifactFromNexus(locationPath, targetPath, packageName)
        if locationPath !=nil
           downloadCMD="cd #{targetPath};wget #{locationPath}"
           Utils.logged_exec(downloadCMD,"deployment_cbt.downloadArtifactFromNexus", true) 
           
           if packageName !=nil
             oldName=(locationPath.split('/')).last
             changeNameCMD="cd #{targetPath}; mv #{oldName} #{packageName}"
             Utils.logged_exec(changeNameCMD,"deployment_cbt.downloadArtifactFromNexus.changePackageName from #{oldName} to #{packageName}", true) 
           end
        end
    end
    
    # #########################
    # download artifact git
    # #########################
    def downloadArtifactFromGit(locationPath, targetPath)
         if locationPath !=nil
           downloadCMD="cd #{targetPath};git #{locationPath}"
           Utils.logged_exec(downloadCMD,"deployment_cbt.downloadArtifactFromGit", true)
         end
    end 
    
    # #########################
    # download artifact from internet
    # #########################
    def downloadArtifactByWget(locationPath, targetPath)
         if locationPath !=nil
           downloadCMD="cd #{targetPath};wget #{locationPath}"
           Utils.logged_exec(downloadCMD,"deployment_cbt.downloadArtifactbyWget from #{locationPath}", true)
         end
    end      
    
    # #########################
    # aggregate from each node
    # #########################
    def aggregateArtifact(nodeInfoArray, artifactMap, role)         
        
        _aggregateArtifactMap=Hash.new              
        nodeInfoArray.each do |node|        
                if role.include?("app")
                      if node["wars"] !=nil
                             warsArr=node["wars"].split(",")
                             warsArr.each do |warName|
                                _location=getArtifactLocation(artifactMap, "wars", warName)
                                _artifact=getArtifactName(warName, "war", Depac::DeploymentConstants_CBT::WAR_FORMAT)
                                
                                if !(_aggregateArtifactMap.has_key?(warName))
                                   _aggregateArtifactMap[warName]={"location" => _location,
                                                                   "packageName" => _artifact,
                                                                   "localLocation" => nil
                                                                  }
                                end
                             end                    
                      end
                      
                elsif role.include?("db")
                 
                      if node["schema"] !=nil
                             schemaArr=node["schema"].split(",")
                             schemaArr.each do |schemaName|
                                _location=getArtifactLocation(artifactMap, "schema", schemaName)
                                _artifact=getArtifactName(schemaName, "schema", nil)
                                
                                if !(_aggregateArtifactMap.has_key?(schemaName)) 
                                         _aggregateArtifactMap[schemaName]={"location" => _location,
                                                                            "packageName" => _artifact,
                                                                            "localLocation" => nil
                                                                           }
                                end                                
                             end                    
                      end
                end
         end    
         return _aggregateArtifactMap
    end
       
    # ##################################
    # generate official war package name as format sample: trade-web-1.0.0-SNAPSHOT.war
    # ##################################
    def getArtifactName(artifactName, type, format)   
          artifactPackageName=artifactName
    
          case type
          
          when 'war'
             #artifactPackageName = artifactname+format+buildlabel
             artifactPackageName = artifactName+"-web" unless artifactName == "passport-cas" || artifactName == "passport-reg"
            
          else
             Depac::Log.write("INFO", "artifact package name don't need to transfer") 
          end          
          return artifactPackageName
    end
    
    
    # ##########################
    #sample:
    #wars:
    #   cart: http://nexus:8081/....
    #   payment: http:...
    #schema:
    #   cart: git://....
    #   payment: git://....
    # ##########################
    #This method used to get artfiact location through cbt-artifact-location.yml
    def getArtifactLocation(artifactMap, type, name)
          locationPath=nil
          if artifactMap.has_key?(type)
                     artifactListMap=artifactMap[type]                   
                     if artifactListMap.has_key?(name)
                        locationPath = artifactListMap[name]
                     end
          end 
          Depac::Log.write("INFO", "Find #{type}-->#{name} location->#{locationPath} ......")          
          return locationPath
    end    
    
    
    def generateContainerServiceRegistry(envconfig,buildlabel)
        Depac::Log.info("deployment_cbt.generateContainerServiceRegistry....") 
        
        if envconfig['registerCenter'] != nil
          template = File.read("templates/container-service-registry.xml.erb")
          template = Erubis::Eruby.new(template) 
        
          containerServiceRegistryConfig = template.result(
                     :registerCenter =>  envconfig['registerCenter']       
          )
                  
          filename=Depac::DeploymentConstants_CBT::DefaultArtifactLocation+"/#{buildlabel}/temp/container-service-registry.xml"
          Depac::Log.write("INFO", "generate ContainerServiceRegistry. remove eixst container-service-registry.xml file if it exist......")   
          system("rm -rf #{filename}")
                  
          #Depac::Log.debug("generate web-module-resources-default.property final hashMap is: #{webModuleHash_Default}......")
          File.open(filename, "w") {|f|
                     f.puts(containerServiceRegistryConfig)
                     f.close
          }
        else
          Depac::Log.info("deployment_cbt.generateContainerServiceRegistry: can not find specified registerCenter....") 
        end
    end    
    
    # This is abstract method to generate the source file for each component
    def generateResource(nodeInfoMap, appNode, buildlabel, _war, envconfig)     
      if File.exist?(Depac::DeploymentConstants_CBT::CBT_WAR_RESOURC_MAPPING_PATH)  
               Depac::Log.info("deployment_cbt.generateResource.........")   
               warRSMap_Hash=YAML.load_file(File.expand_path(Depac::DeploymentConstants_CBT::CBT_WAR_RESOURC_MAPPING_PATH))           
               if warRSMap_Hash.has_key?(_war)  
                 Depac::Log.info("deployment_cbt.generateResource: get property collection for war #{warRSMap_Hash[_war]}.........")
                 warRSMap_Hash[_war].each do |propertyName, relatedPath|
                      
                         case propertyName
                           
                         when "web-module-resources.properties"
                            generateWebModuleProperty(nodeInfoMap, appNode, buildlabel, _war)
                         when "container-service-registry.xml"
                            generateContainerServiceRegistry(envconfig,buildlabel)
                         when "cas.properties"
                            generateCASProperty(nodeInfoMap, appNode, buildlabel, _war)
                         else
                           Depac::Log.info("Don't know how to handle this property-> #{propertyName}! ignore it!") 
                         end
                    end                 
               end
      end
    end   
    
    
    
    def generateCASProperty(nodeInfoMap, node, buildlabel, _war)
             Depac::Log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") 
             Depac::Log.info("deployment_cbt.generateCASProperty: cas.properties for #{_war} on server #{node['hostname']}")
                 
             template = File.read("templates/cbt-passport-cas.properties.erb")
             template = Erubis::Eruby.new(template) 
             
             default_jdbc_db_ip="localhost"
             
             if node !=nil && node['linkto'] != nil 
                   Depac::Log.info("deployment_cbt.generateCASProperty: current node linto is #{node['linkto']}")             
                   node['linkto'].each do |roleInfo|
                     roleInfo.each do |role, linktoinfo|
                         Depac::Log.info("deployment_cbt.generateCASProperty: current role is #{role}")
                         if role == "db-mysql"
                           Depac::Log.info("deployment_cbt.generateCASProperty: find db-mysql link")
                           temp_db=getLinkedIP(linktoinfo,role,nodeInfoMap)
                           Depac::Log.info("deployment_cbt.generateCASProperty: get linkto db IP is #{temp_db}")
                           default_jdbc_db_ip=temp_db
                           break
                         end
                     end
                   end 
             end
            
             casConfig = template.result(
                     :passport_cas_ip =>  node['IP'],         
                     :jdbc_db_ip =>  default_jdbc_db_ip
             )
                  
             filename=Depac::DeploymentConstants_CBT::DefaultArtifactLocation+"/#{buildlabel}/temp/cas.properties"
             Depac::Log.write("INFO", "generate cas.properties remove eixst property file if it exist......")   
             system("rm -rf #{filename}")
                  
             File.open(filename, "w") {|f|
                     f.puts(casConfig)
                     f.close
             }                  
             Depac::Log.write("INFO", "generate cas.properties done for #{node['hostname']}......") 
             Depac::Log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")             
    end    
    
    # ##################################
    #
    #  "hostname": "20150624-1049-qa-qc-app-tomcat-1",
    #  "chefnodename": "20150624-1049-qa-qc-app-tomcat-1",
    #  "chefroles": [
    #    "cbt_stone_tomcat"
    #  ],
    #  "vmid": "i-j83dd1tc",
    #  "war": "trade",
    #  "linkto": 
    #        [
    #         "activemq": {index: nil, IP: nil, config: nil}}
    #         "redis": {index: nil, IP: nil, config: nil}}
    #         "db-mysql": {index: nil, IP: nil, config: nil}
    #        ]
    #  "IP": "192.168.100.5"
    #
    #  ##################################
    #generate data source pool property based on erb template
    #so far just need to detect db type and redis type
    def generateWebModuleProperty(nodeInfoMap, node, buildlabel, warName)
          Depac::Log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") 
          Depac::Log.info("deployment_cbt.deployApp: generateWebModuleProperty for #{warName} on server #{node['hostname']}") 
          
          
          
          #1. load cbt-web-module-resource-default.yml
          #2. this would be a webModuleHash_Default
          #3. generate a webModuleHash_Cust 
          #4. go through app-tomcat rol   
          
          webModuleHash=Hash.new
          webModuleHash_Default=YAML.load_file(File.expand_path(Depac::DeploymentConstants_CBT::CBT_WEB_MODEL_RESOURCE_DEFAULT_YAML))
          webModuleHash_Cust={
                                "jdbc"=>{},
                                "redis_pool"=>{},
                                "redis_dbindex"=>{},
                                "message_server"=>{}
                             }
          
          if node !=nil && node['linkto'] != nil
          
              node['linkto'].each do | linkRoleInfo |
              
                    linkRoleInfo.each do |role, linkInfo|
                         
                           case role
                           
                           when "db-mysql"
                              Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: detected link role -->#{role} in #{node['hostname']}, will handle it!")
                              Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: link role -->#{role} configure is #{linkInfo}")
                              
                              _ip=nil
                              
                              if linkInfo != nil
                                if linkInfo['config'] !=nil
                                    webModuleHash_Cust.merge! linkInfo['config']
                                end
                              
                                
                                #if linkInfo['IP'] !=nil
                                #     _ip = linkInfo['IP']
                                #elsif linkInfo['index'] != nil
                                #    _ip=getIPbyRoleAndIndex(nodeInfoMap, role, linkInfo['index'])   
                                #else
                                #    Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: can not find specified ip for #{role}, will find it in new provisioned VM.........")
                                #    _ip=getIPbyRoleAndIndex(nodeInfoMap, role, 0)
                                # end 
                                _ip=getLinkedIP(linkInfo,role,nodeInfoMap)
                            
                              else
                                 Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: can not find specified ip for #{role}, will find it in new provisioned VM.........")
                                 _ip=getIPbyRoleAndIndex(nodeInfoMap, role, 0)                      
                              end
                              
                              if _ip !=nil
                                   Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: get link role #{role} with IP-->#{_ip}.........")                                   
                                   webModuleHash_Cust['jdbc']['jdbc_db_ip']=_ip
                              end 
                           when "redis"
                              Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: detected link role-->#{role} in #{node['hostname']}, will handle it!") 
                              _ip=nil
                              
                              if linkInfo != nil
                                if linkInfo['config'] !=nil
                                    webModuleHash_Cust.merge! linkInfo['config']
                                end
                              
                                
                                #if linkInfo['IP'] !=nil
                                #     _ip = linkInfo['IP']
                                #elsif linkInfo['index'] != nil
                                #    _ip=getIPbyRoleAndIndex(nodeInfoMap, role, linkInfo['index'])   
                                #else
                                #    Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: can not find specified ip for #{role}, will find it in new provisioned VM.........")
                                #    _ip=getIPbyRoleAndIndex(nodeInfoMap, role, 0)
                                #end  
                                _ip=getLinkedIP(linkInfo,role,nodeInfoMap)
                                
                                     
                             else
                                 Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: can not find specified ip for #{role}, will find it in new provisioned VM.........")
                                 _ip=getIPbyRoleAndIndex(nodeInfoMap, role, 0)                                                         
                             end
                             
                             if _ip !=nil
                                 Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: get link role #{role} with IP-->#{_ip}.........")
                                 webModuleHash_Cust['redis_pool']['redis_ip']=_ip
                             end
                             
                           when "mq"
                             Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: detected link role-->#{role} in #{node['hostname']}, will handle it!") 
                                 _ip=nil
                                                           
                                 if linkInfo != nil                                                                  
                                                             
                                     #if linkInfo['IP'] !=nil
                                     #     _ip = linkInfo['IP']
                                     #elsif linkInfo['index'] != nil
                                     #    _ip=getIPbyRoleAndIndex(nodeInfoMap, role, linkInfo['index'])   
                                     #else
                                     #    Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: can not find specified ip for #{role}, will find it in new provisioned VM.........")
                                     #    _ip=getIPbyRoleAndIndex(nodeInfoMap, role, 0)
                                     #end      
                                     _ip=getLinkedIP(linkInfo,role,nodeInfoMap)
                                   
                                    
                                 else
                                      Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: can not find specified ip for #{role}, will find it in new provisioned VM.........")
                                      _ip=getIPbyRoleAndIndex(nodeInfoMap, role, 0)                                                         
                                 end
                                                          
                                 if _ip !=nil
                                      Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: get link role #{role} with IP-->#{_ip}.........")
                                      webModuleHash_Cust['message_server']['mq_ip']=_ip
                                 end                           
                           else
                              Depac::Log.write("INFO", "deployment_cbt.generateWebModuleProperty: detected link role-->#{role} in #{node['hostname']}, but it is not the target to generate web module property. Ignore it!")                 
                           end
                    end
              end
            
            
            #webModuleHash= webModuleHash_Default.merge webModuleHash_Cust
            
            if webModuleHash_Cust['jdbc'] !=nil
                 webModuleHash_Cust['jdbc'].each do |key, value|
                       webModuleHash_Default['jdbc'][key]=value
                 end 
            end 
            
            if webModuleHash_Cust['redis_pool'] !=nil
                webModuleHash_Cust['redis_pool'].each do |key, value|
                       webModuleHash_Default['redis_pool'][key]=value
                 end 
            end
            
            if webModuleHash_Cust['redis_dbindex'] !=nil
                webModuleHash_Cust['redis_dbindex'].each do |key, value|
                       webModuleHash_Default['redis_dbindex'][key]=value
                 end 
            end
            
            if webModuleHash_Cust['message_server'] !=nil
                webModuleHash_Cust['message_server'].each do |key, value|
                       webModuleHash_Default['message_server'][key]=value
                 end 
            end
            
            
            Depac::Log.write("INFO", "generate web-module-resources-default.property final hashMap is: #{webModuleHash_Default}.......")
            
            template = File.read("templates/web-module-resources-default.erb")
            template = Erubis::Eruby.new(template) 
            
            if warName == "calculation" || warName=="trade"
                 _warName="mysql"
            else
                 _warName=warName
            end 
            
            webModuleConfig = template.result(
               :jdbc_db_driver =>  webModuleHash_Default['jdbc']['jdbc_db_driver'],         
               :jdbc_db_ip => webModuleHash_Default['jdbc']['jdbc_db_ip'],
               :jdbc_db_username => webModuleHash_Default['jdbc']['jdbc_db_username'],       
               :jdbc_db_password => webModuleHash_Default['jdbc']['jdbc_db_password'], 
               :jdbc_pool_initialSize => webModuleHash_Default['jdbc']['jdbc_pool_initialSize'],
               :jdbc_pool_maxActive => webModuleHash_Default['jdbc']['jdbc_pool_maxActive'],
          
               :redis_pool_maxActive=> webModuleHash_Default['redis_pool']['redis_pool_maxActive'], 
               :redis_pool_maxIdle => webModuleHash_Default['redis_pool']['redis_pool_maxIdle'],        
               :redis_pool_maxWait => webModuleHash_Default['redis_pool']['redis_pool_maxWait'],
               :redis_pool_testOnBorrow => webModuleHash_Default['redis_pool']['redis_pool_testOnBorrow'],
        
               :redis_ip => webModuleHash_Default['redis_pool']['redis_ip'],
               :redis_port => webModuleHash_Default['redis_pool']['redis_port'],
                
               :component => _warName
               
              )
            
            filename=Depac::DeploymentConstants_CBT::DefaultArtifactLocation+"/#{buildlabel}/temp/web-module-resources.properties"
            Depac::Log.write("INFO", "generate web-module-resources-default.property remove eixst property file if it exist......")   
            system("rm -rf #{filename}")
            
            Depac::Log.debug("generate web-module-resources-default.property final hashMap is: #{webModuleHash_Default}......")
            File.open(filename, "w") {|f|
               f.puts(webModuleConfig)
               f.close
            }
           
           Depac::Log.write("INFO", "generate web-module-resources-default.property merge #{warName}.redis.index to property file......") 
           system("cat ./templates/#{warName}.redis.index >> #{filename}")
           
           #just for member-web additional configure of ftp server and nginx
           
           Depac::Log.write("INFO", "insert #{warName} additional configure from templates/member.additional.web-module......") 
           system("cat templates/#{warName}.additional.web-module >> #{filename}")
          

           Depac::Log.write("INFO", "generate web-module-resources-default.property done for #{node['hostname']}......")         
       end 
       Depac::Log.info(">>>>>>>>>>>>>>>>>")
     end
     
     def getLinkedIP(linkInfo,role,nodeInfoMap)
              _ip=nil
                        
              if linkInfo['IP'] !=nil
                  _ip = linkInfo['IP']
              elsif linkInfo['index'] != nil
                  _ip=getIPbyRoleAndIndex(nodeInfoMap, role, linkInfo['index'])   
              else
                 Depac::Log.write("INFO", "deployment_cbt.getLinkedIP: can not find specified ip for #{role}, will find it in new provisioned VM.........")
                 _ip=getIPbyRoleAndIndex(nodeInfoMap, role, 0)
              end 

              return _ip
     end
     
            
  end
end